package middleware

import (
	"encoding/json"
	"fmt"
	"mldong/api/auth"
	"mldong/api/base"
	"mldong/internal/consts"
	"mldong/utility"
	"strings"

	"github.com/gogf/gf/v2/container/garray"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"
	"github.com/golang-jwt/jwt/v5"
)

func init() {
	RegisterMiddleware(AuthMiddleware, 10)
}

// 权限认证中间件
func AuthMiddleware(r *ghttp.Request) {
	// 可以通过这个方法获取请求的handler，然后获取其meta标签，判断是否需要权限认证，这里先不实现
	handler := r.GetServeHandler()
	noLogin := handler.GetMetaTag("noLogin")
	// 如果meta标签存在noLogin，则直接通过
	if noLogin == "true" {
		r.Middleware.Next()
		return
	}
	// 如果为白名单请求，则直接通过
	for _, pattern := range consts.WhiteList {
		if utility.MatchAntPath(pattern, r.URL.Path) {
			r.Middleware.Next()
			return
		}
	}
	var TokenPrefix = consts.TokenPrefix
	var tokenString = r.Header.Get(consts.TokenName)
	// 去掉TokenPrefix
	if len(tokenString) <= len(TokenPrefix) {
		r.Response.WriteJson(base.Fail(99990403, "token无效"))
		r.Exit()
	}
	tokenString = tokenString[len(TokenPrefix):]

	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
		return []byte(consts.JwtKey), nil
	})
	if err != nil || !token.Valid {
		fmt.Println(err)
		r.Response.WriteJson(base.Fail(99990403, "token无效"))
		r.Exit()
	}
	// 从 JWT 中提取 PermCodes
	claims, ok := token.Claims.(jwt.MapClaims)
	if !ok {
		r.Response.WriteJson(base.Fail(99990403, "token无效"))
		r.Exit()
	}
	var user = auth.LoginUserVO{}
	jsonData, _ := json.Marshal(claims)
	json.Unmarshal(jsonData, &user)
	// 设置用户信息
	r.SetCtxVar(consts.UserInfoKey, user)
	if user.SuperAdmin {
		r.Middleware.Next()
		return
	} else {
		// 黑名单校验
		blacklist, err := g.Cfg().Get(r.Context(), "g.blacklist")
		if err == nil {
			for _, pattern := range blacklist.Array() {
				if utility.MatchAntPath(pattern.(string), r.URL.Path) {
					r.Response.WriteJsonExit(g.Map{
						"code": 99990406,
						"msg":  "您没有资源访问权限，请联系管理员！",
					})
					return
				}
			}
		}
	}
	// 如果meta标签存在noPerm，则直接通过
	noPerm := handler.GetMetaTag("noPerm")
	if noPerm == "true" {
		r.Middleware.Next()
		return
	}
	// 如果为忽略权限名单请求，则直接通过
	for _, pattern := range consts.IgnoreAuthList {
		if utility.MatchAntPath(pattern, r.URL.Path) {
			r.Middleware.Next()
			return
		}
	}
	permCodeList := user.PermCodes
	perm := handler.GetMetaTag("perm")
	permMode := handler.GetMetaTag("mode")
	authMap := consts.AuthMap
	if perm != "" {
		mode := "and"
		if permMode != "" {
			mode = permMode
		}
		authMap[r.URL.Path] = map[string]string{
			"value": perm,
			"mode":  mode,
		}
	}
	// 获取请求路径对应的权限规则
	authRule, exists := authMap[r.URL.Path]
	if exists {
		// 如果存在权限规则，则根据规则进行校验
		requiredPerms := strings.Split(authRule["value"], ",")
		mode := authRule["mode"]
		if mode == "" {
			// 如果没有指定模式，则使用默认模式（or）
			mode = "or"
		}
		fmt.Println("mode:" + mode)
		if mode == "or" {
			// or 模式：用户只需拥有任意一个权限码即可
			var hasPerm bool
			for _, perm := range requiredPerms {
				if garray.NewStrArrayFrom(permCodeList).Contains(perm) {
					hasPerm = true
					break
				}
			}
			if !hasPerm {
				r.Response.WriteJson(base.Fail(99990406, "权限不足"))
				r.Exit()
			}
		} else if mode == "and" {
			// and 模式：用户需拥有所有权限码
			for _, perm := range requiredPerms {
				if !garray.NewStrArrayFrom(permCodeList).Contains(perm) {
					r.Response.WriteJson(base.Fail(99990406, "权限不足"))
					r.Exit()
				}
			}
		}
	} else {
		// 如果不存在权限规则，则使用默认规则
		permCode := strings.Replace(strings.Replace(r.URL.Path, "/", ":", -1), ":", "", 1)
		if !garray.NewStrArrayFrom(permCodeList).Contains(permCode) {
			r.Response.WriteJson(base.Fail(99990406, "权限不足"))
			r.Exit()
		}
	}
	r.Middleware.Next()
}
